package com.eugenema.demand;

import com.eugenema.entity.TestStep;
import com.eugenema.enumEntity.StepAction;
import com.eugenema.service.RunSeleniumService;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialog;
import javafx.scene.control.Tooltip;
import org.kordamp.ikonli.javafx.FontIcon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
/**
 * <p>标题：需求抽象类</p>
 * <p>功能：包含需求所必须的方法，对外提供统一的调用方法</p>
 * <p>
 * 其他说明：
 * <br/> 所有需求都应该继承该抽象类，并增加 @DemandBean 注解，为 key、title、order 赋值
 * <br/> 其中 key 用于唯一标识该需求，title 用于显示需求名称，order 用于排序，若 order 重复，则会覆盖
 * <br/> 日志对象通过 Logger() 方法获取
 * <br/> 脚本运行服务通过 RunSeleniumService() 方法获取
 * </p>
 * <p>作者：马寅广</p>
 * <p>创建日期：2023/12/31 11:28</p>
 */
public abstract class Demand {
    /** 日志 */
    private static Logger logger = LoggerFactory.getLogger(Demand.class);
    /** 需求池：包含所有需求 */
    public static Demand[] demandPool;
    /** 要解析的 XML 文件名 */
    public static final String PARSE_XML = "GrabMatchData.xml";
    /** 编辑参数按钮 id 前缀 */
    public static final String EDIT_PARAMETER_PREFIX = "editParameter_";
    /** 弹自定义界面按钮 id 前缀 */
    public static final String DIALOG_PREFIX = "dialog_";
    /** 需求唯一键 */
    private String key = "";
    /** 需求名称 */
    private String title = "";
    /** 需求信息 */
    private String notice = "";
    /** 需求顺序 */
    private int order = 0;
    /** 需求按钮列表 */
    private List<JFXButton> buttons = new ArrayList<>();
    /** 创建运行服务 */
    private static RunSeleniumService runSeleniumService;

    /**
     * 获取需求唯一键
     * <br/> 用于在需求池中查找需求
     * <br/> 若为空，则报错
     *
     * @author 马寅广
     * @date 2023/12/31 11:29
     *
     *
     * @return 唯一键
     **/
    public String getKey() {
        if (key.isEmpty()) {
            throw new RuntimeException("需求唯一键不能为空");
        }
        return key;
    }

    /**
     * 设置需求唯一键
     *
     * @author 马寅广
     * @date 2023/12/31 22:18
     *
     * @param key
     *
     * @return
     **/
    public void setKey(String key) {
        this.key = key;
    }

    /**
     * 获取需求名称
     * <br/> 用于在界面中展示需求
     * <br/> 若为空，则报错
     *
     * @author 马寅广
     * @date 2023/12/31 11:31
     *
     *
     * @return 名称
     **/
    public String getTitle() {
        if (title.isEmpty()) {
            throw new RuntimeException("需求名称不能为空");
        }
        return title;
    }

    /**
     * 设置需求名称
     *
     * @author 马寅广
     * @date 2023/12/31 22:18
     *
     * @param title
     *
     * @return
     **/
    public void setTitle(String title) {
        this.title = title;
    }

    /**
     * 获取需求信息
     * <br/> 用于在界面中展示需求信息
     * <br/> 界面初始化、需求执行成功/失败都会触发该方法
     *
     * @author 马寅广
     * @date 2023/12/31 11:46
     *
     *
     * @return 需求信息，可能为空
     **/
    public String getNotice() {
        return notice;
    }

    /**
     * 写入需求信息
     *
     * @author 马寅广
     * @date 2023/12/31 17:41
     *
     * @param notice 需求信息
     *
     **/
    public void setNotice(String notice) {
        this.notice = notice;
    }

    /**
     * 获取需求顺序
     *
     * @author 马寅广
     * @date 2024/1/1 14:06
     *
     *
     * @return 需求顺序
     **/
    public int getOrder() {
        return order;
    }

    /**
     * 设置需求顺序
     *
     * @author 马寅广
     * @date 2024/1/1 14:07
     *
     * @param order 需求顺序
     *
     **/
    public void setOrder(int order) {
        this.order = order;
    }

    /**
     * 获取需求功能按钮
     * <br/> 用于在界面中展示需求功能按钮
     * <br/> 该按钮在运行过程中不可用
     *
     * @author 马寅广
     * @date 2023/12/31 11:41
     *
     *
     * @return 按钮，可能为空
     **/
    public List<JFXButton> getButtons() {
        if (buttons.isEmpty()) {
            initButton();
        }
        return buttons;
    }

    /**
     * 添加按钮
     *
     * @author 马寅广
     * @date 2023/12/31 22:21
     *
     * @param button 按钮
     *
     **/
    public void addButton(JFXButton button) {
        buttons.add(button);
    }

    /**
     * 执行需求
     * <br/> 需求执行的入口
     *
     * @author 马寅广
     * @date 2023/12/31 11:35
     *
     *
     * @return 是否执行成功
     **/
    public boolean run() {
        logger.info("开始执行需求: 【{}】", getTitle());
        RunSeleniumService().openBrow();
        boolean executeFlag = execute();
        logger.info("执行需求: 【{}】，结果: 【{}】", getTitle(), executeFlag ? "成功" : "失败");
        return executeFlag;
    }

    /**
     * 需求方法体
     * <br/> 需求执行的具体逻辑
     *
     * @author 马寅广
     * @date 2023/12/31 20:52
     *
     * @return 执行结果
     **/
    public abstract boolean execute();

    /**
     * 初始化按钮
     *
     * @author 马寅广
     * @date 2023/12/31 19:30
     *
     **/
    public abstract void initButton();

    /**
     * 按钮公共方法：打开生成的文件
     *
     * @author 马寅广
     * @date 2023/12/31 20:42
     *
     * @param fileName 要打开的文件名，包括扩展名
     *
     **/
    public void openFile(String fileName) {
        TestStep testStep = new TestStep();
        testStep.setId("手动打开文件");
        testStep.setDesc(String.format("打开【%s】文件", fileName));
        testStep.setAction(StepAction.CMD_OPEN_EXCEL_FILE);
        testStep.setValue(fileName);

        RunSeleniumService().runStep(testStep);
    }

    /**
     * 获取日志对象
     *
     * @author 马寅广
     * @date 2023/12/31 21:33
     *
     *
     * @return 日志对象
     **/
    public Logger Logger() {
        return logger;
    }

    /**
     * 获取运行服务
     *
     * @author 马寅广
     * @date 2023/12/31 21:44
     *
     *
     * @return 运行服务
     **/
    public RunSeleniumService RunSeleniumService() {
        if (runSeleniumService == null) {
            runSeleniumService = new RunSeleniumService(PARSE_XML);
        }
        return runSeleniumService;
    }

    /**
     * 增加默认编辑参数按钮
     * <br/> 将按钮自动增加到按钮列表
     * <br/> 具体执行方法可以参考：HomeDetailController#createDemandList.318
     *
     * @author 马寅广
     * @date 2024/1/1 12:08
     *
     **/
    public void createEditParameterButton() {
        JFXButton button = new JFXButton();
        button.getStyleClass().add("radiuButton");
        // 图标
        FontIcon fontIcon = new FontIcon();
        fontIcon.setIconLiteral("fi-pencil");
        fontIcon.setIconSize(20);
        fontIcon.getStyleClass().add("button-icon");
        button.setGraphic(fontIcon);
        // 提示信息
        button.setTooltip(new Tooltip("编辑参数"));
        // 点击事件，绑定控制器提供的方法
        button.setId(EDIT_PARAMETER_PREFIX + getKey());
        addButton(button);
    }

    /**
     * 增加默认打开文件按钮
     * <br/> 将按钮自动增加到按钮列表
     *
     * @author 马寅广
     * @date 2024/1/1 12:26
     *
     * @param fileName 要打开的文件名，包括扩展名
     *
     **/
    public void createOpenFileButton(String fileName) {
        JFXButton button = new JFXButton();
        button.getStyleClass().add("radiuButton");
        // 图标
        FontIcon fontIcon = new FontIcon();
        fontIcon.setIconLiteral("fi-page-csv");
        fontIcon.setIconSize(20);
        fontIcon.getStyleClass().add("button-icon");
        button.setGraphic(fontIcon);
        // 提示信息
        button.setTooltip(new Tooltip("打开生成的文件"));
        // 附属信息
        button.setOnAction(action -> openFile(fileName));
        addButton(button);
    }

    /**
     * 创建自定义弹窗按钮
     * <br/> 该方法与 createCustomDialog 方法绑定，即使用该方法，需要重写 createCustomDialog
     *
     * @param title 按钮名称
     * @param iconCode 按钮图标
     *
     * @author 马寅广
     * @date 2024/1/1 14:31
     *
     **/
    public void createCustomDialogButton(String title, String iconCode) {
        JFXButton button = new JFXButton();
        button.getStyleClass().add("radiuButton");
        // 图标
        FontIcon fontIcon = new FontIcon();
        fontIcon.setIconLiteral(iconCode);
        fontIcon.setIconSize(20);
        fontIcon.getStyleClass().add("button-icon");
        button.setGraphic(fontIcon);
        // 提示信息
        button.setTooltip(new Tooltip(title));

        // 点击事件，通过 HomeDetailController 绑定方法
        button.setId(DIALOG_PREFIX + getKey());
        addButton(button);
    }

    /**
     * 若需自定义按钮，请重写此方法
     * <br/> 返回一个自定义的 JFXDialog
     *
     * @author 马寅广
     * @date 2024/1/1 14:58
     *
     *
     * @return
     **/
    public JFXDialog createCustomDialog() {
        return null;
    }
}
